Overshadowing with Get and Set Methods*976*

Farmer Brown is in the habit of prefacing the name of his young cows with the qualifier “Lil’,” as in “Lil’ Elsie is over yonder.” The researchers decide to incorporate this idiosyncrasy into their diary reports.

You can accomplish this by creating an overshadowing Get method for the name attribute of the Cow class and its subclasses. Whenever you access the name attribute of a Cow-type instance, the overshadowing get name method checks the instance’s age attribute and prefixes the string, Lil’, to the name string if the instance is three years old or younger.

To create a Get method to overshadow the name attribute of the Cow class, do the following:

u
Command-click to create a new method icon in the Cow Methods window, select Get from the Opers menu, and type name. This action creates the special name method icon.

u
Open the get name method and create the following two cases (comments optional).

___________________________________________________________
NOTE:  Like its Get primitive counterpart, the Get method has a single input root bringing in the instance that is having its attribute accessed and two output terminals. The left terminal passes along the instance and the right passes along the value of the attribute retrieved after whatever required preprocessing is performed. 

Get and Set methods are designed for specific operations on attribute values, but there really are no restrictions on the processing that can be done inside a Get method. It is possible to create Get methods that do anything and everything you want without bothering to get and pass along the requested attribute value. Such a “masquerading” Get method works but it is stylistically bad form. Unless you have some overpowering rationale, use overshadowing Get and Set methods for their intended purposes only.
-----------------------------------------------------------

If you run the Barnyard Simulation now, young Cow instances are not given their new names. There are a few subtle edits you must make to your existing code to enable your application to access the get name overshadowing method.

u
Open the Cow/talk method and add a slash character, /, in front of the word, name, in the Get operation.

u
Do the same edit, changing name to /name, in the Get name operations in the move, sleep, eat, and birthday methods of the Animal class. It does not matter if you make this edit in the Animal/talk method, as the Cow class has its own overshadowing talk method, which you have already modified.

___________________________________________________________
NOTE:  To access an overshadowing*387* Get or Set method, you must include a data-driven *2**3*slash*275* notation before the name of the attribute in the Get or Set operation. The slash notation triggers Prograph to look for a Get or Set method rather than use its built-in primitive to access the attribute.*988**989*

You can prevent the overshadowing by using a non-slash prefixed attribute name in a Get or Set operation. When no slash is present, Prograph uses the built-in primitive Get or Set capabilities even when a Get or Set method is defined. 

You do not need to worry about other subclass instances of Animal using the edited Animal methods. If an instance has the attribute named in a slash-prefixed Get or Set operation but there is no such Get or Set method defined, Prograph simply ignores the slash and performs a Get or Set operation on the named attribute using the built-in primitives. Therefore, it is safe to add slash notation to the get name operations in the Animal class methods even though no classes other than Cow and its subclasses have the get name method defined.
-----------------------------------------------------------

Creating a Set method is very similar to doing a Get method. To reflect the popular notion about “dog years” being in a ratio of seven to one calendar years, overshadow the setting of the age attribute in the Dog class.

u
Open the Dog Methods window and create a Set method named age and then open its case window.

u
Since the birthday-calculating local method in Barnyard/action already adds one to each animal who has a birthday, the Dog/age Set method should add six to the age value that is passed to it as the new age for a Dog instance.

u
To put the Dog aging factor into effect, open the inc age local method in the Animal/birthday method and edit the Set age operation to be a Set /age operation.
Now when your Barnyard inhabitants celebrate a birthday, Dog instances age by a factor of seven, consistent with the popular notion of a dog’s life. (To keep Dog ages as a factor of seven, open the activeYards inhabitants list and directly edit the age attribute of any existing Dog instance by multiplying its current age by seven.)

u
The Barnyard Simulation has reached a new level of complexity. Run the simulation and observe the results of your changes. A collage of typical DiaryEntry and herd report Value windows are pictured at the top of the following page.

If you want to get a closer look at what is going on as the simulation runs, don’t forget about the wide range of Step/Show, Breakpoint, and Stack window capabilities at your disposal as presented in the previous tutorial.

u
Stop running the simulation and save your work before considering the challenge.

You have successfully elaborated your discrete event simulation into one incorporating a complex class hierarchy using attribute and method inheritance and overshadowing. As you can see, object-oriented programming is an efficient and appropriate medium for developing simulations.

In addition, you now have the technical background to more fully appreciate the structure and function of the System classes that are the foundation of Prograph’s Application Builder. Having seen the trees rather than being overwhelmed by the forest with regard to Prograph classes, you are now better prepared to understand the upcoming tutorial on Application Builder. Before moving on, challenge your current understanding of Prograph’s classes below and then extend your knowledge and skills in developing Prograph methods in the next tutorial.

t
Challenge: Abstract Classes

*151*Take a closer look at your Barnyard Simulation Animal class hierarchy. Is there anything other than the depth of the inheritance tree that distinguishes these classes from each other? If you noticed that some of the classes are specific kinds of animals and some are categories of animals, you are on the right track.

The Animal, Bird, and Cow classes help define subclasses of animals, but they are not themselves specific species of animals. There is no generic bird:  a bird is a crow, robin, hawk, or sparrow (ignoring the complexity of the categorization of subspecies of these animals). A cow is some kind of cow. In the Barnyard Simulation, a cow should be either a Guernsey or Black Angus class instance.

There is a term in object-oriented*866* programming*774* for classes that are used to help build other classes but that are not intended to be used for the creation of instances directly. Such classes are called abstract classes.

Abstract classes have been known to confuse those learning object-oriented programming. Some OOP environments utilize large, complex hierarchies of system classes, many of which are abstract classes. These abstract classes are used to create clusters of subclasses that share common attributes or behaviors. No instances of such abstract classes are ever created. Trying to determine which classes among all the classes are the abstract ones can be frustrating.

But seen in an appropriate context, abstract classes are not so difficult to understand. The Animal class hierarchy is such an intuitive context. Birds share certain attributes and behaviors. Using the inheritance mechanism, the abstract Bird class provides a lowest-common-denominator definition for bird species. Creating new species of bird as subclasses of the Bird class saves work and ensures that all birds initially meet the minimum criteria of “birdness”—they are like other animals but include a wingspan attribute in this example. For cows, “cowness” now includes a herding mentality unique among the barnyard animals.

As the application designer, you evolve the most useful and efficient class structure for implementing the application in object-oriented terms. In creating your application, you often develop a complex hierarchy of classes or extend Prograph’s System classes. As your application evolves, you may have an explicit, or at least intuitive, understanding of which classes are used to create instances and which are not when your application is run.

In many applications, the underlying class system is only known to you and is not accessible to the application user. The application interface creates only the correct classes of objects. Abstract class instances are not generated because no code has been written that creates such an instance.

But some applications, like the Barnyard Simulation, are more open and accessible to the user. A string entry prompt, "What kind of animal did the farmer buy at the auction?" can be answered with any response that can be typed. Currently, if you enter Animal, Bird, or Cow to the above prompt, an instance of these abstract classes is produced. This design loophole is the source of your challenge.

 Abstract-class Challenge

Your Objective:  Use your knowledge of classes, inheritance, and overshadowing to ensure that abstract-class animal instances are not created when you run the Barnyard Simulation.*0157*

Tips and Hints

q To make sure your solution is on the right track and to avoid confusion, delete any Animal, Bird, or Cow class instances from the Barnyard instance in activeYards before you begin.

q Two basic approaches to your objective are reasonable. One approach would be to rework the interface so constrained choices are offered to the user. Don’t meet your challenge by restricting the interface. The second approach, and the one desired here, is to modify the abstract classes so they do not create instances of themselves.

q Remember the effect of method inheritance. You have to undo the constraint on abstract-class instance creation so subclasses of the abstract class can create instances of themselves.

q Remember that a newly created instance is the input on the root of an overshadowed instance generator, <<>> method, and that the inst-to-list primitive lets you “degenerate” the incoming instance. Also remember that the input to an Instance generator operation can be a list of lists in the form ((attributeName attributeValue) (attributeName attributeValue)).

q A simple way to implement this objective is to arbitrarily change an abstract class instance request into the generation of one of the subclasses of the*16* abstract classes. For example, make all Bird requests into Chicken instances. A more complex implementation utilizes an injected instance generator. 

===========================================================
TIP:  An inject annotated terminal gives an operation a name at runtime. A string is expected as input to the inject terminal; that string then becomes the name of the operation when it is executed. Refer to the Reference manual for further information on injection.
 ===========================================================

q Hint:  If you are stuck, selective loading of a particular Animal method gets you going.

Solution to Challenge

Solution Comments:  Overshadowing the instance generator with the Animal/<<>> method is the key to implementing this objective. Inheritance allows the Bird and Cow abstract classes to refuse to create instances like their parent. A simple “pass through” of the instance is all that is needed in the Instance method, <<>>, for each Animal subclass that should generate instances.

In the Animal/<<>> method, by decomposing the incoming Animal instance with inst-to-list and by using a list-annotated pack operation, you collect the attribute values for the alternative instance without having to put the user through all the attribute-value input prompts again.

The attribute/value list is fed into a local method, new instance, where a show operation informs the user that animals of the indicated type are not available. The ask prompt then solicits an alternative class. The string returned from the ask prompt is then *483*injected into an Instance generator operation, which creates an instance of the alternative class. If this second response is another abstract class, this same interaction occurs until an acceptable response is given.

Did you remember to copy the Cow/<<>> method to both the Guernsey and Black Angus subclasses before deleting the Cow/<<>> method so inheritance would provide instance-generation prohibition of the abstract Cow class?

t
Check Your Progress

*158*Check the list below. Be sure you are familiar with the concepts presented in this chapter before you go on.

In this tutorial, you have learned how to:

4 differentiate between class attributes and instance attributes in both form and function

4 use the principle of inheritance to create subclasses from classes

4 overshadow inherited class attributes and methods

4 overshadow Instance, Get, and Set operations

4 use Super annotation of a method to inherit a method’s behavior and then add to it

4 use Value windows to edit attribute values and to create instances of classes

4 create a class-based discrete-event simulation using Prograph’s object-oriented capabilities

4 create and use abstract classes for efficient development and organization of subclasses

Don’t hesitate to review the activities you covered in this tutorial before going on to the next chapter. The more comfortable you can become with the basics of the Prograph language classes, the more quickly you can begin to develop your own complex applications. When you are ready to delve into Prograph methods, continue on to the next tutorial.